package com.szgd.aop;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.szgd.util.StringUtil;
import com.szgd.util.Token;

@Aspect
@Component
public class ControllerRepeatAspect {

	private Logger logger = Logger.getLogger(getClass());

	@Pointcut("@annotation(com.szgd.util.Token)")
	public void ControllerRepeat() {
	}

	
	@Before("ControllerRepeat()")
	public void doBefore(JoinPoint joinPoint) throws Throwable {

		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(),
				methodSignature.getMethod().getParameterTypes());

		// 接收到请求，记录请求内容
		ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		HttpServletRequest request = attributes.getRequest();

		Token annotation = method.getAnnotation(Token.class);
		if (annotation != null) {
			boolean needSaveSession = annotation.begin();
			if (needSaveSession) {
				request.getSession(true).setAttribute("token", UUID.randomUUID().toString());
			}
			String needJsonSession = annotation.json();
			if (StringUtil.isNotBlank(needJsonSession)) {
				// 获取参数, 只取自定义的参数, 自带的HttpServletRequest, HttpServletResponse不管
				if (joinPoint.getArgs().length > 0) {
					for (Object o : joinPoint.getArgs()) {
						if (o.getClass().getName().equals(needJsonSession)) {
							if (isRepeatSubmit(request, o)) {
								throw new Exception("重复提交！");
							}
							request.getSession(true).removeAttribute("token");
							break;
						}
					}
				}
			}
			boolean needRemoveSession = annotation.form();
			if (needRemoveSession) {
				if (isRepeatSubmit(request, null)) {
					throw new Exception("重复提交！");
				}
				request.getSession(true).removeAttribute("token");
			}
		}
		
	}

	private boolean isRepeatSubmit(HttpServletRequest request,Object clz) {
		String serverToken = (String) request.getSession(true).getAttribute("token");
		if (StringUtil.isBlank(serverToken)) {
			return true;
		}
		String clinetToken = null;
		if (clz != null) {
			try {
				PropertyDescriptor pd = new PropertyDescriptor("token", clz.getClass());
				Object result = pd.getReadMethod().invoke(clz);
				clinetToken = (String) result;
			} catch (Exception e) {
				e.printStackTrace();
			}
		} else {
			clinetToken = request.getParameter("token");
		}
		if (StringUtil.isBlank(clinetToken)) {
			return true;
		}
		if (!serverToken.equals(clinetToken)) {
			return true;
		}
		return false;
	}

	@AfterReturning(returning = "ret", pointcut = "ControllerRepeat()")
	public void doAfterReturning(Object ret) throws Throwable {
		// 处理完请求，返回内容
		logger.info(ret);
	}
	
}